<template>
  <el-container>
    <vHeadSpace />
    <el-container>
      <vAsideSpace />
      <el-container>
        <el-main class="mapedit-main">
          <div class="map-left-content">
            <!-- 主内容-头部  -->
            <div class="main_head">
              <div class="left-head-views">
                <el-select size="small" v-model="tuopuOptionsCurrent" clearable @change="selectChanged($event)">
                  <el-option v-for="item in tuopuOptions" :key="item.sysmapid" :label="item.name" :value="item">
                  </el-option>
                </el-select>
                <button @click="toggleFullscreen" class="topButton"
                  style="background-color: #F0F2F5;color: black">全屏</button>
                <button class="topButton" @click="deleteCurrentTuoputu">删除</button>
                <button class="topButton" @click="saveTopu">保存</button>
                <button class="topButton" @click="buildOrchangeTopo('change')">修改</button>
                <button class="topButton" @click="buildOrchangeTopo('build')">新建</button>
              </div>
            </div>
            <!-- 主内容-下部分  -->
            <div id="settingBody" class="map_body">
              <button v-if="this.fullscreen == true" class="exitScreen" v-on:keyup.esc="console.log('exit')"
                @click="toggleFullscreen">退出全屏</button>

              <!-- 主内容-上部分-工具栏  -->
              <div class="main_head_tool">
                <button class="mediaButton" @click="chooseEngines">设备添加</button>
                <!--                <button class="mediaButton" @click = "topoInitCreate">自动拓扑</button>-->
              </div>
              <el-divider class="divider-tool"></el-divider>

              <!-- 主内容-上部分-拓扑图编辑工具栏  -->
              <div class="main_head_tool" style="text-align: center">
                <el-button type="text" style="margin-left:10px;padding-top: 2px" @click="makeCenter">居中</el-button>
                <el-button type="text" style="margin-left:10px;padding-top: 2px" @click="deleteChooseNode">删除
                </el-button>
                <el-divider direction="vertical" style=""></el-divider>
                <span style="color: black;">&nbsp;网格：
                  <el-button size="medium" type="text" :value="isGridShow?'隐藏':'显示'" @click="isGridShow=!isGridShow">显示
                  </el-button>
                </span>
                <el-divider direction="vertical"></el-divider>
                <span style="color: black;">连线:&nbsp;
                  <el-button size="medium" type="text" @click="createLink" style="margin: 0 5px">添加</el-button>
                </span>
                <el-divider direction="vertical"></el-divider>
                <el-button type="text" style="padding-top: 2px" @click="zoomOut">放大</el-button>
                <el-button type="text" style="padding-top: 2px" @click="zoomIn">缩小</el-button>
                <el-tooltip content="图标恢复默认大小" placement="top" effect="light">
                  <el-button type="text" style="padding-top: 2px" @click="resetIconSize">重置</el-button>
                </el-tooltip>
                <el-divider direction="vertical"></el-divider>
                <span style="color: black">模式：
                  <el-select size="mini" style="margin-top: 2px;width: 80px" v-model="stageMode"
                    @change="stageModeselectChanged($event)">
                    <el-option v-for="item in stageModes" :key="item.model" :label="item.name" :value="item">
                    </el-option>
                  </el-select>
                </span>
              </div>
              <el-divider class="divider-tool"></el-divider>

              <!-- 主内容-下部分-拓扑图  -->
              <div class="map-body-content">
                <!-- 主内容-下部分-更右元素选择列表  -->
                <div class="map-body-lefter-room">
                  <!--                      <el-button type="text" size="small" icon="el-icon-edit" @click="elementChooseChange"-->
                  <!--                                 style="background-color: #133b5c;width: 100%;color:white">文字添加-->
                  <!--                      </el-button>-->
                  <el-button type="text" size="small" icon="el-icon-s-platform" @click="elementChooseChange"
                    style="background-color: #133b5c;width: 100%;margin-left: 0;margin-top: 1px;color:white">
                    设备添加
                  </el-button>
                  <textarea id="jtopo_textfield" style="display:none;width: 60px;position: absolute;"
                    onkeydown="if(event.keyCode==13)this.blur();"></textarea>
                  <el-divider class="el_divider"></el-divider>
                  <div v-show="hostElementVisable" style="width: 100%;">
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <img width="24" height="18" style="margin-left: 4px" draggable="false"
                        :src="topoImgSrc.switch.path" />
                      <span style="font-size: 12px;margin-left: 4px;cursor: move">交换机</span>
                    </div>
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <img width="24" height="18" style="margin-left: 4px" draggable="false"
                        :src="topoImgSrc.server.path" />
                      <span style="font-size: 12px;margin-left: 4px;cursor: move">服务器</span>
                    </div>
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <img width="24" height="18" style="margin-left: 4px" draggable="false"
                        :src="topoImgSrc.firewall.path" />
                      <span style="font-size: 12px;margin-left: 4px;cursor: move">防火墙</span>
                    </div>
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <img width="24" height="18" style="margin-left: 4px" draggable="false"
                        :src="topoImgSrc.gatekeeper.path">
                      <span style="font-size: 12px;margin-left: 4px;cursor: move">单向网闸</span>
                    </div>
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <img width="24" height="18" style="margin-left: 4px" draggable="false"
                        :src="topoImgSrc.router.path" />
                      <span style="font-size: 12px;margin-left: 4px;cursor: move">路由器</span>
                    </div>
                  </div>
                  <div v-show="wordElementVisable" style="width: 100%;">
                    <div class="divelement" style="margin: 6px 0" draggable="true" @dragstart="dragStart($event)">
                      <i class="iconfont icon-wenzi"></i>
                      <span style="font-size: 12px;cursor: move">文字</span>
                    </div>
                  </div>
                </div>

                <!-- 主内容-下部分-左边拓扑图内容  -->
                <div class="map-main-body">
                  <canvas @drop="drop($event)" @dragover="allowDrop($event)" id="canvas" style="float: left"
                    :class="isGridShow?'mapCanvas-content':'noGrid'">
                  </canvas>
                </div>

                <div class="node-edit-dialog" v-show="nodeEditDialogVisable">
                  <div>
                    设备名称:<el-input size="mini" v-model="nodeName" maxlength="15"></el-input>
                  </div>
                  <div style="margin-top: 6px">
                    设备关联:<br>
                    <el-select size="mini" style="width: 100%" :disabled="nodeNameChange"
                      v-model="nodeEditSelectHostName" value-key="hostid"
                      @change="(($event)=>{nodeEditSelectHost=$event})">
                      <el-option v-for="item in nodeEditSelect" :key="item.hostid" :label="item.hostName" :value="item"
                        :disabled="item.disabled">
                      </el-option>
                    </el-select>
                  </div>
                  <el-divider class="node-edit-divider"></el-divider>
                  <div>
                    元素尺寸:<br>
                    <div class="long">
                      长(20~120):<br>
                      <pre>   </pre>
                      <el-input-number size="mini" v-model="hostSize.width" :min="20" :max="120"></el-input-number>
                    </div>
                    <div class="width">
                      宽(20~120):<br>
                      <pre>   </pre>
                      <el-input-number size="mini" v-model="hostSize.height" :min="20" :max="120"></el-input-number>
                    </div>
                  </div>

                  <div style="width: 100%;position: absolute;bottom: 0;">
                    <el-divider class="node-edit-divider"></el-divider>
                    <div style="float: right">
                      <el-button type="plain" size="mini" @click="nodeEditDialogVisable=!nodeEditDialogVisable">关闭
                      </el-button>
                      <el-button type="primary" size="mini" @click="makeSure">确认</el-button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-main>
        <vFootSpace />
      </el-container>
    </el-container>

    <!-- 物理机选择弹窗 -->
    <el-dialog custom-class="tree-dialog-settings" title="设备添加" :modal-append-to-body="false" :lock-scroll="false"
      :visible.sync="dialogEngineChooseVisible">
      <el-input placeholder="输入查找主机名(区分大小写)" v-model="filterText" style="margin-top: 10px" size="small" maxlength="15">
      </el-input>
      <div style="overflow: auto;height: 300px;margin-top: 10px">
        <el-tree :data="hostLists" :props="defaultProps" show-checkbox node-key="id" :filter-node-method="filterNode"
          ref="tree">
          <span class="custom-tree-node" slot-scope="{node}">
            <span>{{ node.label }}</span>
            <span v-if="node.label!=='交换机' && node.label!=='主机' && isAvailable(node.label)==='可用'">可用</span>
            <span v-else-if="node.label!=='交换机' && node.label!=='主机' && isAvailable(node.label)==='不可用'">不可用</span>
            <span v-else-if="node.label!=='交换机' && node.label!=='主机'">未知</span>
          </span>
        </el-tree>
      </div>
      <div style="flex-shrink: 0;margin-top:6px;text-align: right;">
        <el-button size="mini" @click="resetChecked">重置选择</el-button>
        <el-button type="primary" size="mini" @click="getCheckedNodes">确认选择</el-button>
        <el-button type="danger" size="mini" @click="dialogEngineChooseVisible=!dialogEngineChooseVisible">退出选择
        </el-button>
      </div>
    </el-dialog>

    <!-- 拓扑图创建弹窗 -->
    <el-dialog title="拓扑图创建" :visible.sync="addTopo_dialogFormVisible">
      <div class="topology-create-dialog">
        <el-form :model="topology" :rules="rules" ref="ruleForm">
          <el-form-item label="拓扑名称:" :label-width="topologyLabelWidth" prop="name">
            <el-input size="medium" v-model="topology.name" autocomplete="off" maxlength="15"></el-input>
          </el-form-item>
          <!--          <el-form-item label="刷新频率:" :label-width="topologyLabelWidth">-->
          <!--            <el-input size="medium" v-model="topology.speed" autocomplete="off"></el-input>-->
          <!--          </el-form-item>-->
          <!--          <el-form-item label="告警显示:" :label-width="topologyLabelWidth">-->
          <!--            <el-radio-group v-model="topology.warningShow">-->
          <!--              <el-radio label="是"></el-radio>-->
          <!--              <el-radio label="否"></el-radio>-->
          <!--            </el-radio-group>-->
          <!--          </el-form-item>-->
          <el-form-item label="网格显示:" :label-width="topologyLabelWidth">
            <el-switch v-model="topology.gridShow"></el-switch>
          </el-form-item>
        </el-form>
        <div class="topology-create-dialog-footer">
          <el-button @click="cancelForm('ruleForm')" size="medium">取 消</el-button>
          <el-button type="primary" size="medium" @click="createTopology('ruleForm')">确 定</el-button>
        </div>
      </div>
    </el-dialog>
  </el-container>
</template>

<style scoped>
.mapedit-main {
  height: 92vh;
  width: 100%;
  margin-top: 56px;
  padding: 10px;
}

.map-left-content {
  height: 97%;
  overflow: hidden
}

/*<!-- 主内容-上部分  -->*/
.main_head {
  width: 100%;
}

.topButton {
  border: 0;
  background-color: #133b5c;
  color: white;
  float: right;
  position: relative;
  margin-right: 10px;
  margin-top: 7px;
}

.mediaButton {
  border: 0;
  background-color: #133b5c;
  color: white;
  float: left;
  margin-top: 5px;
  margin-left: 10px
}

.el-select {
  display: inline-block;
  position: absolute;
  margin-top: 0;
}

/*<!-- 主内容-上部分-视图切换栏  -->*/
.left-head-views {
  background-color: #F0F2F5;
  width: 100%;
  height: 38px;
}

/*<!-- 主内容-上部分-工具栏  -->*/
.main_head_tool {
  background-color: white;
  width: 100%;
  height: 32px;
}

/*<!-- 主内容-下部分  -->*/
.map_body {
  width: 100%;
  height: 91%;
}

/*<!-- 主内容-下部分-更右元素选择列表  -->*/
.map-body-lefter-room {
  border: 0.5px solid white;
  border-right-color: #EEEEEE;
  background-color: white;
  width: 12%;
  height: 98%;
}

.el_divider {
  margin: 4px 0 !important;
}

.divider-tool {
  margin: 0 !important;
}

.node-edit-divider {
  margin-top: 34px;
  margin-bottom: 4px;
}

.divelement:hover {
  background-color: #F0F2F5;
  cursor: move;
  /*transition: all 0.8s ease;*/
}

/*<!-- 主内容-下部分-左边拓扑图内容  -->*/
.map-main-body {
  /*display: flex;*/
  background-color: white;
  width: 88%;
  height: 98%;
}

/* 节点编辑弹窗 */
.node-edit-dialog {
  position: absolute;
  right: 10px;
  background-color: #F0F2F5;
  /*background-color: red;*/
  /*height: 71vh;*/
  width: 12%;
  z-index: 10;
}

.mapCanvas-content {
  background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.1) 2%, rgba(0, 0, 0, 0) 2%), linear-gradient(360deg, rgba(50, 0, 0, 0.1) 2%, rgba(0, 0, 0, 0) 2%);
  background-size: 26px 26px;
  background-repeat: repeat;
  background-position: center center;
}

.el-tree {
  min-width: 100%;
  display: inline-block;
}

.el-dialog__body {
  padding: 0;
}

pre {
  display: inline;
}

.long {
  width: 10rem;
  height: 4rem;
  margin: 0 auto;
}

.width {
  width: 10rem;
  height: 4rem;
  margin: 0 auto;
}

.exitScreen {
  width: 6rem;
  height: 2rem;
  position: absolute;
  left: 86rem;
  border: 0;
}

.map-body-content {
  display: flex;
  height: 92%;
}

.map_edit {
  text-align: center;
  background-color: white;
  height: 32px;
}

.topology-create-dialog {
  /*width: 50%;*/
}

.topology-create-dialog-footer {
  position: absolute;
  right: 20px;
  bottom: 18px;
}
</style>
<style>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.tree-dialog-settings {
  background-color: #F0F2F5;
  width: 30%;
}

.el-dialog__body {
  padding-top: 0;
  padding-bottom: 20px;
}

.el-checkbox:last-of-type {
  margin-right: 8px;
  margin-bottom: 0;
}

.el-tabs__item {
  padding-left: 20px !important;
}
</style>
<script src="../../../public/js/jquery.min.js"></script>
<script>
// import TopoMenu from "@/views/topology/TopoMenu";
import axios from 'axios'
import {topoImgSrc} from "../../../public/js/topoImgSrc.js"

export default {
    name: "TopoSetting",
    data() {
        var validateName = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('注意输入不能为空！'));
            } else {
                // if (this.topology.name !== '') {
                //   this.$refs.ruleForm.validateField('checkPass');
                // }
                callback();
            }
        };
        return {
            canvas: {},
            stage: {}, //舞台
            scene: {}, //场景
            createOrUpdateFlag: "build",
            isGridShow: true,
            stageMode: '编辑',
            stageModes: [{name: "编辑", mode: "edit"}, {name: "框选", mode: "select"}, {name: "拖动", mode: "drag"}],
            canvasWidth: document.body.clientWidth * 0.778,
            canvasHeight: document.body.clientHeight * 0.716,
            dialogEngineChooseVisible: false,
            hostLists: [{
                label: '主机',
                children: [],
            }, {
                label: '交换机',
                children: []
            }],
            defaultProps: {
                children: 'children',
                label: 'label'
            },
            currentChooseHost: [],
            currentChooseNode: null,
            hostContents: [], // 临时存放关于节点的一些内容
            filterText: '',
            nodeIdIndex: [],// 保存节点text,selementid,icon_ff信息
            hostElementVisable: true,
            wordElementVisable: false,
            imgSrc: null,
            imgLabel: '',
            fullscreen: false,
            tuopuOptionsCurrent: '无可展示拓扑图',
            currentChooseTuopu: {},// 当前拓扑图信息
            tuopuOptions: [],
            addTopo_dialogFormVisible: false,
            topology: {
                name: '',
                speed: '',
                gridShow: true,
                warningShow: "是"
            },
            topologyLabelWidth: '80px',
            topoImgSrc: topoImgSrc,
            nodeEditDialogVisable: false,
            nodeEditSelect: [{
                hostid: '',
                hostName: '',
                disabled: null
            }],
            nodeName: '',
            nodeEditSelectHostName: '',
            nodeEditSelectHost: null,
            nodeNameChange: false,
            hostSize: {// 节点尺寸
                width: '',
                height: ''
            },
            isChangedFlag: false,
            rules: {
                name: [
                    {validator: validateName, trigger: 'blur'}
                ],
            },
        }
    },
    components: {
        // TopoMenu,
    },
    methods: {
        // 重置所有图标大小
        resetIconSize() {
            let currentNodeList = this.scene.getDisplayedElements();
            if (currentNodeList.length !== 0) {
                for (let i = 0; i < currentNodeList.length; i++) {
                    if(currentNodeList[i] instanceof JTopo.Node){
                        currentNodeList[i].setSize(Math.round(parseInt(this.canvasWidth) * 0.012) * 3, Math.round(parseInt(this.canvasWidth) * 0.012) * 3)
                    }
                }
                // 修改标记
                this.isChangedFlag = true
            }
        },

        // 乌龟绘图-将所添加的设备节点放至指定位置
        autolocation(nodes) {
            let _this = this
            let hostType = null;
            let node = null;
            let length = 0;
            // 乌龟每走一步留下的脚印被解释为: 在x，y处增加一个节点
            let tortoise = new Logo.Tortoise((x, y) => {
                if (length < nodes.length) {
                    hostType = _this.checkHostType(nodes[length].snmp_available)
                    let node = _this.addNode(nodes[length].host, null, null, hostType, null, nodes[length].hostid);
                    node.setCenterLocation(x, y);
                    length += 1;
                }
            });

            // 步长缩放20倍，即：两个脚印相隔20个像素（默认为1个像素）
            tortoise.resize(90);

            // 方形
            let rectangle = (t, n) => {
                // 向前走 n 步
                t.forward(1);

                // 旋转90度
                t.turn(Math.PI / 2);
                // 向前走 n 步
                for (let i = 0; i < n; i++) {
                    t.forward(1);
                }

                t.turn(-Math.PI / 2);
                // 向前走 1 步
                t.forward(1);

                t.turn(-Math.PI / 2);
                // 向前走 n 步
                for (let i = 0; i < n; i++) {
                    t.forward(1);
                }
            }

            // 先移动到画布起始点
            tortoise.moveTo(_this.canvasWidth * 0.004, _this.canvasHeight * 0.04);
            rectangle(tortoise, 5);
        },

        // 设备可用性判断
        isAvailable(name) {
            if (this.hostContents !== null) {
                for (let i = 0; i < this.hostContents.length; i++) {
                    if (this.hostContents[i].hostInf.host === name) {
                        if (this.hostContents[i].hostInf.snmp_available === '1' || this.hostContents[i].hostInf.available === '1') {
                            return '可用';
                        } else return "不可用";
                    }
                }
            }
            return "未知";
        },

        // 更改当前操作模式
        stageModeselectChanged(e) {
            // console.log(e);
            this.stageMode = e.name;
            this.stage.mode = e.mode;

        },

        // 放大
        zoomOut() {
            this.stage.zoomOut();
        },

        // 缩小
        zoomIn() {
            this.stage.zoomIn();
        },

        // 缩放并居中显示
        makeCenter() {
            if (this.scene.getDisplayedElements().length !== 0) {
                this.stage.centerAndZoom();
            }
        },

        // 拓扑图编辑或者修改操作
        buildOrchangeTopo(operation) {
            this.createOrUpdateFlag = operation // 记录当前操作类型
            if (operation === 'build') {
                // 初始化
                this.topology.name = ""
                this.topology.gridShow = true

                this.addTopo_dialogFormVisible = true;
            } else if (operation === 'change') {
                // 回显当前拓扑图的信息
                this.topology.name = this.currentChooseTuopu.name
                this.topology.gridShow = this.isGridShow

                this.addTopo_dialogFormVisible = true;
            }
        },

        // 节点编辑验证
        makeSure() {
            let node = this.currentChooseNode
            // 修改标记
            this.isChangedFlag = true

            // 输入设备名称是否唯一
            let flag = false
            let elements = this.scene.getDisplayedElements();
            elements.forEach((element) => {
                if (element instanceof JTopo.Node && element.text === this.nodeName && element !== node) {
                    flag = true
                    this.$message({
                        message: "注意节点名称已存在，请重新命名",
                        duration: 1500,
                        type: 'warning'
                    })
                }
            })
            // 名称修改
            if (!flag) {
                // 同步更新nodeIdIndex中该节点名称,以及关联的设备hostid(若选择)
                for (let i = 0; i < this.nodeIdIndex.length; i++) {
                    if (node.text === this.nodeIdIndex[i].host) {
                        this.nodeIdIndex[i].host = this.nodeName;
                        // 设备关联
                        if (this.nodeEditSelectHost != null) {
                            this.nodeIdIndex[i].hostid = this.nodeEditSelectHost.hostid
                            // 更新已被选择标记
                            this.updateHostChooseFlag()
                        }
                        break
                    }
                }
                node.text = this.nodeName
            }
            // 尺寸修改
            if (this.hostSize.width !== '' && this.hostSize.height !== '') {
                node.setSize(parseInt(this.hostSize.width), parseInt(this.hostSize.height))
                flag?1:this.nodeEditDialogVisable = false;
            } else {
                this.$message({
                    message: '注意尺寸输入不能为空',
                    duration: 1500,
                    type: 'warning'
                })
            }
        },

        // 创建拓扑图
        createTopology(formName) {
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    if (this.createOrUpdateFlag === 'build') {// 创建操作
                        // 保存
                        let grid_show = 0;// 0-显示，1-不显示
                        if (!this.topology.gridShow) {
                            grid_show = 1
                        }
                        this.isGridShow = this.topology.gridShow
                        axios({
                            method: "post",
                            url: "map/createMap.action",
                            data: {
                                name: this.topology.name,
                                width: Math.round(this.canvasWidth),
                                height: Math.round(this.canvasHeight),
                                grid_show: grid_show,
                            }
                        }).then((res) => {
                            // console.log(res);
                            if(res.data.errorCode == null){
                                this.tuopuOptions.push({
                                    "name": this.topology.name,
                                    "sysmapid": res.data.content.sysmapids[0]
                                })

                                // 新拓扑图更新至拓扑列表中
                                this.selectChanged({
                                    name: this.topology.name,
                                    sysmapid: res.data.content.sysmapids[0]
                                })

                                this.$message.success('创建成功')
                                this.addTopo_dialogFormVisible = false;
                            } else {
                                this.$message.warning(res.data.errorCode)
                            }
                        }).catch((err) => {
                            console.log(err);
                        })
                    } else if (this.createOrUpdateFlag === 'change') {// 修改操作
                        // 名称唯一性判断
                        let index = 0
                        for (let i = 0; i < this.tuopuOptions.length; i++) {
                            if (this.tuopuOptions[i].name === this.topology.name) {
                                index++
                                if (index == 2) {
                                    this.$message.warning('注意当前名称已存在！请重新命名');
                                    break;
                                }
                            }
                        }
                        if (index != 2) {
                            this.currentChooseTuopu.name = this.topology.name
                            // 更新拓扑图列表展示
                            for (let i = 0; i < this.tuopuOptions.length; i++) {
                                if (this.tuopuOptions[i].name === this.topology.name) {
                                    this.tuopuOptions[i].name = this.topology.name;
                                    break;
                                }
                            }
                            this.tuopuOptionsCurrent = this.topology.name
                            this.isGridShow = this.topology.gridShow
                            this.saveTopu();
                        }
                    }
                } else {
                    return false;
                }
            });
        },

        cancelForm(formName) {
            // 表单验证重置
            this.$refs[formName].resetFields();
            this.addTopo_dialogFormVisible = false;
        },

        // 删除当前拓扑图
        deleteCurrentTuoputu() {
            this.$confirm('确认删除拓扑图 “' + this.currentChooseTuopu.name + '”，注意删除后不可恢复', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.$axios({
                    method: "get",
                    url: "map/deleteMap.action",
                    params: {
                        sysmapid: this.currentChooseTuopu.sysmapid
                    },
                }).then((response) => {
                    // console.log(response);
                    if(response.data.errorCode == null){
                        this.$message({message: '删除成功', type: 'success'});

                        // 清空当前拓扑图的元素信息
                        this.nodeIdIndex = []

                        // 重新获取所有拓扑图
                        this.getAllTuopu()
                    } else this.$message.warning(response.data.errorCode)

                }).catch(() => {
                    this.$message({
                        type: 'error',
                        message: '删除失败'
                    });
                })
            }).catch(() => {
                this.$message({
                    type: 'info',
                    message: '已取消删除'
                });
            })
        },

        // 拓扑图列表切换时
        selectChanged(val) {
            // 切换前，对当前内容进行一次自动保存
            this.saveTopu("NO");
            this.tuopuOptionsCurrent = val.name
            this.currentChooseTuopu = {
                name: val.name,
                sysmapid: val.sysmapid
            }
            // 清空保存的拓扑图节点信息
            this.nodeIdIndex = []
            // 关闭节点编辑弹窗
            this.nodeEditDialogVisable = false

            this.paintTopoMapBySysmapids(val.sysmapid)
        },

        // 获取所有拓扑图
        getAllTuopu() {
            axios.get('map/getAllMap.action').then((res) => {
                // console.log(res);
                if (res.data.content.result != null) {
                    if(res.data.content.result.length != 0){
                        this.tuopuOptions = []
                        res.data.content.result.forEach((item) => {
                            this.tuopuOptions.push({"name": item.name, "sysmapid": item.sysmapid})
                        })
                        this.tuopuOptionsCurrent = this.tuopuOptions[0].name
                        this.currentChooseTuopu = this.tuopuOptions[0]
                        // 展示拓扑图
                        this.paintTopoMapBySysmapids(this.tuopuOptions[0].sysmapid)
                    } else {
                        // 清空相应标志，赋初始值
                        this.tuopuOptions = []
                        this.tuopuOptionsCurrent = '无可展示拓扑图'
                        this.currentChooseTuopu = {}

                        // 所有设备状态恢复为未关联
                        this.updateHostChooseFlag()

                        // 清空当前画布
                        if (this.scene.getDisplayedElements().length !== 0) {
                            this.deleteElements(this.scene.getDisplayedElements())
                        }
                    }
                }

            }).catch((err) => {
                console.log(err);
                this.$message.warning("拓扑图列表更新失败！")
            })

        },

        // 创建文字对象
        createWordObject(text, x, y) {
            let textNode = new JTopo.TextNode("双击修改文字");
            textNode.font = '14px Calibri';
            textNode.fontColor = '0,0,0'
            textNode.editAble = false;
            textNode.setLocation(x, y);
            this.scene.add(textNode);
        },

        // 开始拖动
        dragStart(event) {
            // console.log(event);
            // console.log("拖动开始")
            event.dataTransfer.setData("imgSrc", event.target.firstChild.currentSrc);
            event.dataTransfer.setData("imgLabel", event.target.innerText);
        },

        // 正在拖动
        allowDrop(event) {
            event.preventDefault();
            // console.log("拖动")
        },

        // 拖动完成
        drop(event) {
            event.preventDefault();
            this.imgSrc = event.dataTransfer.getData("imgSrc")
            this.imgLabel = event.dataTransfer.getData("imgLabel")
        },

        // 元素选择库切换
        elementChooseChange(e) {
            if (e.target.innerText == "文字添加") {
                this.wordElementVisable = true
                this.hostElementVisable = false
            } else if (e.target.innerText == "设备添加") {
                this.wordElementVisable = false
                this.hostElementVisable = true
            }
        },

        // 根据拓扑图sysmapids获取拓扑图内容，并绘制拓扑图
        paintTopoMapBySysmapids(sysmapids) {
            // console.log("绘制拓扑图开始！");
            let mapParams = {}
            axios.get('map/getMapBySysmapids.action', {
                params: {
                    sysmapids: sysmapids
                }
            }).then((res) => {
                // console.log(res.data.content);
                if (res.data.content.result != null && res.data.content.result.length != 0) {
                    mapParams = res.data.content.result[0]

                    // 清空当前画布
                    if (this.scene.getDisplayedElements().length !== 0) {
                        this.deleteElements(this.scene.getDisplayedElements())
                    }
                    // 控制网格显示
                    mapParams.grid_show === "0" ? this.isGridShow = true : this.isGridShow = false;

                    // 创建节点并进行连线
                    let currentNodeList = []
                    if (mapParams.selements.length !== 0) {
                        let Node = null
                        for (let i = 0; i < mapParams.selements.length; i++) {
                            // 元素尺寸
                            let size = {"width": mapParams.selements[i].width, "height": mapParams.selements[i].height}

                            if (mapParams.selements[i].elements.length != 0) {
                                Node = this.addNode(mapParams.selements[i].label, null, mapParams.selements[i].selementid, mapParams.selements[i].iconid_off, null, mapParams.selements[i].elements[0].hostid, size)
                            } else {
                                Node = this.addNode(mapParams.selements[i].label, null, mapParams.selements[i].selementid, mapParams.selements[i].iconid_off, null, null, size)
                            }

                            Node.setLocation(parseInt(mapParams.selements[i].x), parseInt(mapParams.selements[i].y))
                            currentNodeList.push(Node)
                        }

                        let nameList = []
                        let nodeList = []
                        for (let i = 0; i < mapParams.links.length; i++) {
                            // 遍历索引看该节点是否存在，存在则获得其Node对象并连线
                            nameList = []
                            mapParams.selements.forEach((node) => {
                                if (node.selementid === mapParams.links[i].selementid1 || node.selementid === mapParams.links[i].selementid2) {
                                    nameList.push(node.label)
                                }
                                if (nameList.length === 2) {
                                    return 0
                                }
                            })
                            nodeList = []
                            currentNodeList.forEach((item) => {
                                if (item.text === nameList[0] || item.text === nameList[1]) {
                                    nodeList.push(item)
                                }
                                if (nodeList.length === 2) {
                                    return 0
                                }
                            })
                            this.addLink(nodeList[0], nodeList[1])
                        }
                        // 拓扑图整体居中（执行此函数时，拓扑图中至少存在一个节点对象）
                        currentNodeList.length != 0 ? this.stage.centerAndZoom() : 1;
                    }

                    // 拓扑图绘制完成后，更新hostContents中已被选择标志
                    this.updateHostChooseFlag()
                }

            }).catch((err) => {
                console.log(err);
                this.$message.warning("拓扑图信息获取失败！")
            })
        },

        // 根据当前已创建节点，更新hostContents中已被选择标志
        updateHostChooseFlag() {
            // 初始所有选择标记为未选择（方便删除操作解除设备关联）
            this.hostContents.forEach((item) => {
                item.isChooose = 0
            })

            // 更新hostContents中设备关联标记
            if (this.nodeIdIndex.length != 0) {
                for (let i = 0; i < this.nodeIdIndex.length; i++) {
                    // hostid不为空才进行更新
                    if (this.nodeIdIndex[i].hostid !== "") {
                        for (let j = 0; j < this.hostContents.length; j++) {
                            if (this.hostContents[j].hostInf.hostid === this.nodeIdIndex[i].hostid) {
                                // 更新该标志为已被选择
                                this.hostContents[j].isChooose = 1
                                break;
                            }
                        }
                    }
                }
            }
        },

        /**
         * 保存拓扑图至数据库
         * 其中参数isShowSuccessNotice 控制是否显示拓扑图保存成功提示
         * @param isShowSuccessNotice 默认为-null
         */
        saveTopu(isShowSuccessNotice) {

            this.addTopo_dialogFormVisible = false;
            var selements = []
            var links = []
            if (this.currentChooseTuopu !== null && this.tuopuOptions.length != 0) {
                let elements = this.scene.getDisplayedElements()

                let element = {}
                let link = {}
                let nodeTotal = 0
                // console.log(this.hostContents)
                for (let i = 0; i < elements.length; i++) {
                    element = {}
                    link = {}
                    // if (elements[i] instanceof JTopo.TextNode) {
                    //     // 封装节点信息
                    //     element = {
                    //         "elements": [
                    //             {"hostid": ""}
                    //         ],
                    //         "elementtype": 0,
                    //         "selementid": "text".concat(elements[i]._id.substr(-4)),// 保证唯一性
                    //         "iconid_off": "7",
                    //         "label": elements[i].text,
                    //         "x": Math.round(elements[i].x),
                    //         "y": Math.round(elements[i].y)
                    //     }
                    //     selements.push(element)
                    // } else
                    if (elements[i] instanceof JTopo.Node) {// 封装主机元素
                        nodeTotal++;
                        // 确定主机对应的hostid
                        let hostid = ""
                        for (let j = 0; j < this.nodeIdIndex.length; j++) {
                            if (this.nodeIdIndex[j].host === elements[i].text) {
                                hostid = this.nodeIdIndex[j].hostid
                            }
                        }

                        // 确定主机使用的背景图片以及selementid信息
                        let iconid_off = "5"
                        let selementid = elements[i].text.concat(elements[i]._id.substr(-4))// 保证唯一性
                        if (this.nodeIdIndex.length !== 0) {
                            this.nodeIdIndex.forEach((item) => {
                                if (item.host === elements[i].text) {
                                    iconid_off = item.iconid_off
                                    selementid = item.selementid
                                    return 0
                                }
                            })
                        }
                        // 封装节点信息
                        element = {
                            "elements": [
                                {"hostid": hostid}
                            ],
                            "elementtype": 0,
                            "selementid": selementid,// 保证唯一性
                            "iconid_off": iconid_off,
                            "label": elements[i].text,
                            "x": Math.round(parseInt(elements[i].x)),
                            "y": Math.round(parseInt(elements[i].y)),
                            "height": elements[i].height,
                            "width": elements[i].width
                        }
                        selements.push(element)
                    } else if (elements[i] instanceof JTopo.Link) {// 封装线元素
                        // 获取连线两端两个节点的selementid
                        let selementid1 = ""
                        let selementid2 = ""
                        this.nodeIdIndex.forEach((item) => {
                            if (item.host === elements[i].nodeA.text) {
                                selementid1 = item.selementid
                            } else if (item.host === elements[i].nodeZ.text) {
                                selementid2 = item.selementid
                            }
                            if (selementid1 !== "" && selementid2 !== "") {
                                return 0;
                            }
                        })
                        link = {
                            "selementid1": selementid1,
                            "selementid2": selementid2,
                            "color": "10,204,80",
                        }
                        links.push(link)
                    }
                }

                // 保存条件为：当前所有已创建结点元素必须位于画布可见范围内
                if( nodeTotal != this.nodeIdIndex.length ){
                    this.$message.warning("保存失败！请确认所有结点位于画布可视范围内。")
                    return
                }

                let grid_show = 0;// 0-显示，1-不显示
                if (!this.isGridShow) {
                    grid_show = 1
                }
                let topoMapParams = {
                    "name": this.currentChooseTuopu.name,
                    "sysmapid": this.currentChooseTuopu.sysmapid,
                    "width": Math.round(this.canvasWidth),
                    "height": Math.round(this.canvasHeight),
                    "grid_show": grid_show,
                    "selements": selements,
                    "links": links
                }
                // console.log(JSON.stringify(topoMapParams));
                // console.log(JSON.stringify(this.nodeIdIndex));
                this.$axios({
                    method: "POST",
                    url: "map/updateMap.action",
                    data: topoMapParams
                }).then((response) => {
                    // console.log(response);
                    if (response.data.errorCode != null) {
                        this.$message.error(response.data.errorCode);
                    } else {
                        isShowSuccessNotice == "NO"?1:this.$message.success('拓扑图保存成功');
                        this.isChangedFlag ? this.isChangedFlag = false : 1;
                    }
                }).catch((error) => {
                    console.log(error);
                    this.$message({
                        message: '程序出错！拓扑图保存失败',
                        duration: 1600,
                        type: 'warning'
                    })
                })
            } else {
                this.$message.warning("请先创建拓扑图");
            }
        },

        // 初始化拓扑图
        topoInitCreate() {
            // 当前拓扑图是否为空
            if (this.scene.getDisplayedElements().length !== 0) {
                // 创建的节点中是否已关联设备
                let flag = true
                for (let i = 0; i < this.nodeIdIndex.length; i++) {
                    if (this.nodeIdIndex[i].hostid !== "") {
                        flag = false;
                        break
                    }
                }
                // 未关联
                if (flag) {
                    this.$message({
                        message: '注意节点未与设备关联',
                        duration: 2000,
                        type: 'warning'
                    })
                    // 已关联
                } else {
                    // 此处执行拓扑构建算法，目前为简单的两两相连
                    // this.initTreeLayout(this.currentChooseHost)(不可用)
                    this.$message({
                        message: '该功能正在完善！',
                        duration: 1600,
                        type: 'warning'
                    })
                }
            } else {
                this.$message({
                    message: '未检测到拓扑节点',
                    duration: 2000,
                    type: 'warning'
                })
            }
        },

        // 获得弹窗中选择的树形节点
        getCheckedNodes() {
            this.currentChooseHost = []
            let hostInfor = this.$refs.tree.getCheckedNodes()
            if (hostInfor.length != 0) {
                // 添加设备类型信息
                for (let i = 0; i < hostInfor.length; i++) {
                    for (let j = 0; j < this.hostContents.length; j++) {
                        if (hostInfor[i].label === this.hostContents[j].hostInf.host) {
                            this.currentChooseHost.push(this.hostContents[j].hostInf)
                            // 修改已被选择标记
                            this.hostContents[j].isChooose = 1
                            break;
                        }
                    }
                }
                // 自动添加节点
                if (this.currentChooseHost.length != 0) {
                    this.isChangedFlag = true
                    if (this.scene.getDisplayedElements().length === 0) {
                        this.initNodeLayout(this.currentChooseHost)
                    } else {
                        // this.autolocation(this.currentChooseHost);
                        let hostType = ''
                        let node = null
                        for (let i = 0; i < this.currentChooseHost.length; i++) {
                            hostType = this.checkHostType(this.currentChooseHost[i].snmp_available)
                            node = this.addNode(this.currentChooseHost[i].host, null, null, hostType, null, this.currentChooseHost[i].hostid);
                            node.setLocation(this.canvasWidth * 0.8 * Math.random(), this.canvasHeight * 0.8 * Math.random())// 乘以0.8将随机位置控制在可视范围内
                        }
                    }

                }
            }
            this.dialogEngineChooseVisible = false
        },

        // 对树形节点进行清空重置
        resetChecked() {
            this.$refs.tree.setCheckedKeys([]);
        },

        // 对树形节点进行过滤选择
        filterNode(value, data) {
            if (!value) return true;
            return data.label.indexOf(value) !== -1;
        },

        // 设备选择
        chooseEngines() {
            // this.findAllHosts()
            // 判断当前是否有有效创建的拓扑图
            if (this.tuopuOptions.length != 0) {
                this.hostLists[0].children = []//主机
                this.hostLists[1].children = []//交换机
                for (let i = 0; i < this.hostContents.length; i++) {
                    if (this.hostContents[i].hostInf.snmp_available === '0') {
                        if (this.hostContents[i].isChooose === 0) {
                            this.hostLists[0].children.push({
                                "id": i,
                                "label": this.hostContents[i].hostInf.host,
                                "disabled": false
                            })
                        } else {
                            this.hostLists[0].children.push({
                                "id": i,
                                "label": this.hostContents[i].hostInf.host,
                                "disabled": true
                            })
                        }
                    } else {
                        if (this.hostContents[i].isChooose === 0) {
                            this.hostLists[1].children.push({
                                "id": i,
                                "label": this.hostContents[i].hostInf.host,
                                "disabled": false
                            })
                        } else {
                            this.hostLists[1].children.push({
                                "id": i,
                                "label": this.hostContents[i].hostInf.host,
                                "disabled": true
                            })
                        }
                    }
                }
                this.dialogEngineChooseVisible = true
            } else {
                this.$message.warning("请先创建拓扑图！")
            }
        },

        // 获取当前所有主机
        findAllHosts() {
            axios.get('/host/findAllHost.action').then((res) => {
                // console.log(res);
                this.hostLists[0].children = []//主机
                this.hostLists[1].children = []//交换机
                for (let i = 0; i < res.data.content.hosts.length; i++) {
                    if (res.data.content.hosts[i].snmp_available === '0') {
                        this.hostLists[0].children.push({
                            "id": i,
                            "label": res.data.content.hosts[i].host,
                            "disabled": false
                        })
                    } else {
                        this.hostLists[1].children.push({
                            "id": i,
                            "label": res.data.content.hosts[i].host,
                            "disabled": false
                        })
                    }

                    // 保存主机相关信息,以备他用(加入是否以备选择标记)
                    this.hostContents.push({"isChooose": 0, "hostInf": res.data.content.hosts[i]})
                    // console.log(this.hostContents);
                }
            })
        },

        // 初始化节点树形布局
        initNodeLayout(val) {
            // 清空保存的拓扑图节点信息
            this.nodeIdIndex = []

            let hostType = this.checkHostType(val[0].snmp_available)
            var rootNode = this.addNode(val[0].host, null, null, hostType, null, val[0].hostid);
            rootNode.setLocation(Math.round(this.canvasWidth * 0.5), Math.round(this.canvasHeight * 0.5));
            rootNode.layout = {type: 'circle', radius: 200};

            for (let i = 1; i < val.length; i++) {
                hostType = this.checkHostType(val[i].snmp_available)
                var node = this.addNode(val[i].host, null, null, hostType, null, val[i].hostid);
                this.addLink(rootNode, node);
            }
            // 树形布局
            // this.scene.doLayout(JTopo.layout.TreeLayout('down', 100, 130));
            JTopo.layout.layoutNode(this.scene, rootNode, true);
        },

        // 判断主机类型
        checkHostType(val) {
            if (val === '0') {// 服务器
                return '6'
            } else {// 交换机
                return '1'
            }
        },

        // 参数n为休眠时间，单位为毫秒:
        selfSleep(n) {
            var start = new Date().getTime();
            while (true) {
                if (new Date().getTime() - start > n) {
                    break;
                }
            }
        },

        /**
         * @param text 显示的节点名称
         * @param color 颜色（暂未使用）
         * @param selementid 节点的临时标识号
         * @param icon 节点背景图片
         * @param isAutomaticCreate 是否为自动创建
         * @param hostid 关联主机id
         * @param size 元素尺寸
         * @returns {c|c}
         */
        addNode(text, color, selementid, icon, isAutomaticCreate, hostid, size) {
            this.selfSleep(1);// 延迟一毫秒，防止创建过快，出现重复id情况
            let node = new JTopo.Node(text);
            // 若由用户手动创建节点，则节点名称随机命名
            if (isAutomaticCreate != null && !isAutomaticCreate) {
                node.text = text.concat(node._id.substr(-4))
            }

            node.fontColor = '0,0,0'; // 文字颜色
            hostid == null?node.alpha = 0.5:1;

            // 设置元素尺寸
            // 对图标尺寸进行校验，若超过设定阈值，则重设为默认值
            if(size == undefined || parseInt(size.width) > 120 || parseInt(size.height) > 120){
                node.setSize(Math.round(parseInt(this.canvasWidth) * 0.012) * 3, Math.round(parseInt(this.canvasWidth) * 0.012) * 3)
            } else node.setSize(parseInt(size.width), parseInt(size.height))

            let iconid_off = "5"
            // 设置背景图片(自动创建时)
            if (icon !== null) {
                switch (icon) {
                    case "1":
                        node.setImage(this.topoImgSrc.switch.path)
                        iconid_off = "1"
                        break;
                    case "6":
                        node.setImage(this.topoImgSrc.server.path)
                        iconid_off = "6"
                        break;
                    case "2":
                        node.setImage(this.topoImgSrc.firewall.path)
                        iconid_off = "2"
                        break;
                    case "4":
                        node.setImage(this.topoImgSrc.gatekeeper.path)
                        iconid_off = "4"
                        break;
                    case "3":
                        node.setImage(this.topoImgSrc.router.path)
                        iconid_off = "3"
                        break;
                    default:
                        node.setImage(this.topoImgSrc.cloud.path)
                        iconid_off = "5"
                }
            } else {
                // 根据初始名称，判断其使用图片类型(手动创建时)
                switch (text) {
                    case "交换机":
                        iconid_off = "1"
                        break;
                    case "服务器":
                        iconid_off = "6"
                        break;
                    case "防火墙":
                        iconid_off = "2"
                        break;
                    case "单向网闸":
                        iconid_off = "4"
                        break;
                    case "路由器":
                        iconid_off = "3"
                        break;
                    default:
                        iconid_off = "5"
                }
            }

            this.scene.add(node);

            // 绑定双击编辑事件
            node.dbclick((e) => {
                this.editNode(e)
            });

            // 保存节点text,selementid,icon_ff信息,若已经保存过则更新(新增其关联的hostid)
            // 更新
            let flag = false
            if (this.nodeIdIndex.length !== 0) {
                for (let i = 0; i < this.nodeIdIndex.length; i++) {
                    if (this.nodeIdIndex[i].host === node.text) {
                        selementid == null ? this.nodeIdIndex[i].selementid = text.concat(node._id.substr(-4)) : this.nodeIdIndex[i].selementid = selementid
                        if (hostid != null) {
                            this.nodeIdIndex[i].hostid = hostid
                        }
                        flag = true
                        break
                    }
                }
            }
            // 新增
            if (!flag) {
                this.nodeIdIndex.push({
                    "host": node.text,
                    "hostid": hostid == null ? "" : hostid,
                    "selementid": text.concat(node._id.substr(-4)),
                    "iconid_off": iconid_off
                })
            }
            return node;
        },

        addLink(nodeA, nodeZ) {
            var link = new JTopo.Link(nodeA, nodeZ);
            link.direction = 'vertical'
            link.strokeColor = '164,176,190'
            link.lineWidth = 1;
            this.scene.add(link);
            return link;
        },

        //添加线
        createLink() {
            //获取场景中选中的元素
            let selected = this.scene.selectedElements
            let nodes = []
            let j = 0
            for (let i = 0; i < selected.length; i++) {
                if (selected[i] instanceof JTopo.Node && selected[i].width > 0) {
                    nodes[j++] = selected[i]
                }
            }
            if (j >= 2) {
                // 修改标记
                this.isChangedFlag = true

                let link = this.addLink(nodes[0], nodes[1]);
            } else {
                this.$message({
                    message: '请选择要连线的两个节点',
                    type: 'warning'
                })
            }
        },

        // 编辑节点
        editNode(e) {
            // console.log(e);
            // 保存当前选择节点
            this.currentChooseNode = e.target
            this.nodeName = e.target.text
            // 回显节点尺寸
            this.hostSize.width = e.target.width
            this.hostSize.height = e.target.height

            // ***判断当前节点是否已经关联设备
            // 找到其对应的hostid
            let flag = false
            let hostid = ''
            for (let i = 0; i < this.nodeIdIndex.length; i++) {
                if (this.nodeIdIndex[i].host === this.nodeName) {
                    if (this.nodeIdIndex[i].hostid === "") {// 未关联
                        flag = true
                        break;
                    } else {// 已关联,记录其hostid
                        hostid = this.nodeIdIndex[i].hostid
                        break;
                    }
                }
            }

            // 未关联设备,初始化设备选择列表
            // console.log(this.hostContents);
            if (flag) {
                this.nodeEditSelect = []
                this.nodeNameChange = false
                this.nodeEditSelectHostName = ''
                if (this.hostContents.length !== 0) {
                    for (let i = 0; i < this.hostContents.length; i++) {
                        if (this.hostContents[i].isChooose === 0) {// 遍历当前节点确认已被关联的主机不可在被关联
                            this.nodeEditSelect.push({
                                "hostid": this.hostContents[i].hostInf.hostid,
                                "hostName": this.hostContents[i].hostInf.host + '(' + this.isAvailable(this.hostContents[i].hostInf.host) + ')',
                                "disabled": false
                            })
                        } else {
                            this.nodeEditSelect.push({
                                "hostid": this.hostContents[i].hostInf.hostid,
                                "hostName": this.hostContents[i].hostInf.host + '(' + this.isAvailable(this.hostContents[i].hostInf.host) + ')',
                                "disabled": true
                            })
                        }
                    }
                }
                // 已关联设备,回显其其关联设备,并设置为不可再关联
            } else {
                // 遍历找到其关联设备的名称以便回显
                for (let i = 0; i < this.hostContents.length; i++) {
                    if (this.hostContents[i].hostInf.hostid === hostid) {
                        this.nodeEditSelectHostName = this.hostContents[i].hostInf.host
                        this.nodeNameChange = true
                    }
                }
            }

            this.nodeEditDialogVisable = true
        },

        // 动态连接两个节点
        createLinkdynamic() {
            // 动态连线初始化准备
            var beginNode = null;
            var tempNodeA = new JTopo.Node('tempA');
            tempNodeA.setSize(1, 1);
            var tempNodeZ = new JTopo.Node('tempZ');
            tempNodeZ.setSize(1, 1);
            var link = new JTopo.Link(tempNodeA, tempNodeZ);

            // 连线跟随鼠标移动
            this.scene.mousemove(function (e) {
                tempNodeZ.setLocation(e.x, e.y);
            });

            this.scene.mousedown(e => {
                if (e.target == null || e.target === beginNode || e.target === link) {
                    this.scene.remove(link);
                }
            });

            this.scene.mouseup(e => {
                // 右键取消正在进行的连线
                if (e.button == 2) {
                    beginNode = null;
                    this.scene.remove(link);
                    return;
                }
                if (e.target != null && e.target instanceof JTopo.Node) {
                    if (beginNode == null) {
                        beginNode = e.target;
                        this.scene.add(link);
                        tempNodeA.setLocation(e.x, e.y);
                        tempNodeZ.setLocation(e.x, e.y);
                    } else if (beginNode !== e.target) {
                        var endNode = e.target;

                        var l = new JTopo.Link(beginNode, endNode);

                        this.scene.add(l);
                        beginNode = null;
                        this.scene.remove(link);
                    } else {
                        beginNode = null;
                    }
                } else {
                    this.scene.remove(link);
                }
            });
        },

        // 初始化操作
        init() {
            this.canvas = document.getElementById("canvas")
            this.canvas.height = $(".map-main-body").height()
            this.canvas.width = $(".map-main-body").width()

            // 设置节点编辑弹窗的高度
            $(".node-edit-dialog").css("height", this.canvas.height)

            this.stage = new JTopo.Stage(canvas);
            // this.stage.eagleEye.visible = true// 鹰眼显示
            this.scene = new JTopo.Scene(this.stage);
            this.scene.mode = "edit";

            // 视图绑定基本事件
            document.onkeydown = (event) => {
                var e = event || window.event || arguments.callee.caller.arguments[0];
                if (e && e.keyCode == 46) { // 按 Esc
                    this.deleteChooseNode();
                }
                if (e && e.keyCode == 27) { // 按 Esc
                    console.log("ESC事件");
                }
            }

            // this.dbclickChangeText()

            // 拖拽图标到场景并松开鼠标
            this.stage.mouseover((e) => {
                if (this.imgLabel !== null && this.imgLabel !== "") {
                    if (this.imgLabel !== '文字') {
                        // 修改标记添加
                        this.isChangedFlag = true
                        let node = this.addNode(this.imgLabel, null, null, null, false)
                        node.setImage(this.imgSrc, true);
                        node.setLocation(e.x, e.y);
                        this.imgLabel = null
                        this.imgSrc = null;
                    } else {
                        let nodeText = this.createWordObject(this.imgLabel, e.x, e.y)
                        this.imgLabel = null
                    }
                }
            });
        },

        // 删除选中节点
        deleteChooseNode() {
            // 删除之前释放其已关联的节点(未关联则直接删除)
            let elements = this.scene.selectedElements
            if (elements !== null && elements.length !== 0) {
                // 判断当前节点是否关联设备
                for (let i = 0; i < elements.length; i++) {
                    for (let j = 0; j < this.nodeIdIndex.length; j++) {
                        if (this.nodeIdIndex[j].host === elements[i].text) {
                            // 原取消关联改为-删除该节点在索引中的所有信息
                            this.nodeIdIndex.splice(j,1);
                            break
                        }
                    }
                }
                // 更新关联标记
                this.updateHostChooseFlag();

                // 删除节点
                this.deleteElements(elements)
            } else {
                this.$message({
                    message: "请选择删除对象",
                    duration: 1500,
                    type: 'warning'
                })
            }
        },

        // 删除元素
        deleteElements(Elements) {
            // 修改标记
            this.isChangedFlag = true

            if (Elements !== null && Elements.length !== 0) {
                for (let i = 0; i < Elements.length; i++) {
                    this.scene.remove(Elements[i])
                }
            }
        },

        //判断浏览器是否处于全屏状态 （需要考虑兼容问题）
        checkFull() {
          let isFull = document.mozFullScreen ||
            document.fullScreen ||
            //谷歌浏览器及Webkit内核浏览器
            document.webkitIsFullScreen ||
            document.webkitRequestFullScreen ||
            document.mozRequestFullScreen ||
            document.msFullscreenEnabled
          if (isFull === undefined) {
            isFull = false
          }
          return isFull;
        },

        //全屏点击事件
        toggleFullscreen() {
            // let element = document.documentElement;//设置后就是我们平时的整个页面全屏效果
            let element = document.getElementById('settingBody') || document.documentElement || element;//设置后就是   id==settingBody 的容器全屏
            let _myCanvas = document.getElementById("canvas");
            _myCanvas.setAttribute("width", this.canvasWidth);
            _myCanvas.setAttribute("height", this.canvasHeight);
            if (this.fullscreen) {
                if (document.exitFullScreen) {
                    document.exitFullScreen();
                } else if (document.webkitCancelFullScreen) {
                    document.webkitCancelFullScreen();
                } else if (document.mozCancelFullScreen) {
                    document.mozCancelFullScreen();
                } else if (document.msExitFullscreen) {
                    document.msExitFullscreen();
                }
            } else {
                let myCanvas = document.getElementById("canvas");
                myCanvas.setAttribute("width", document.body.clientWidth * 0.9);
                myCanvas.setAttribute("height", document.body.clientWidth * 0.6);
                if (element.requestFullscreen) {
                    element.requestFullscreen();
                } else if (element.webkitRequestFullScreen) {
                    element.webkitRequestFullScreen();
                } else if (element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                } else if (element.msRequestFullscreen) {
                    // IE11
                    element.msRequestFullscreen();
                }
            }
            this.fullscreen = !this.fullscreen;
        },

        // 双击修改文字
        dbclickChangeText(){
            var textfield = $("#jtopo_textfield");
            this.scene.dbclick((event)=>{
                if(!(event.target instanceof JTopo.TextNode))return;// 普通节点关闭在线编辑功能
                if(event.target == null) return;
                var e = event.target;
                textfield.css({
                    top: event.pageY,
                    left: event.pageX - e.width/2
                }).show().attr('value', e.text).focus().select();
                e.text = "";
                textfield[0].JTopoNode = e;
            });

            $("#jtopo_textfield").blur(function(){
                textfield[0].JTopoNode.text = textfield.hide().val();
            });
        }
    },

    created() {
      let that = this
      window.onresize = function() {
        if (!that.checkFull()) {
          // 退出全屏
          that.fullscreen = false
          this.canvas.height = $(".map-main-body").height()
          this.canvas.width = $(".map-main-body").width()
        }
      }
    },

    mounted() {
        this.init()

        // 页面刷新之后，重新设置画布宽高
        window.addEventListener('load', e => {
            this.canvas.height = $(".map-main-body").height()
            this.canvas.width = $(".map-main-body").width()
        })

        this.getAllTuopu();
        // this.createLinkdynamic();
        // 获取所有主机
        this.findAllHosts()
    },

    beforeRouteLeave(to, from, next) {
        // 判断当前页面是否发生修改动作
        if (this.isChangedFlag) {
            this.$confirm('拓扑图检测到未保存的内容，是否保存修改？', '确认信息', {
                distinguishCancelAndClose: true,
                confirmButtonText: '保存',
                cancelButtonText: '放弃修改'
            }).then(() => {
                // 拓扑图保存
                this.saveTopu()
                next()
            }).catch(action => {
                next()
            });
        } else {
            next()
        }
    },

    watch: {
        //监听鼠标选项变化
        // radioMode(newMode, oldMode) {
        //   this.stage.mode = newMode
        // },
        filterText(val) {
            this.$refs.tree.filter(val);
        }
    },
}
</script>